#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include "Util.hpp"
#include <jsoncpp/json/json.h>

//#define MYSELF 1

namespace protocol_ns{
    using namespace std;
    #define SEP " "
    #define SEP_LEN strlen(SEP)
    #define HEADER_SEP "\r\n"
    #define HEADER_SEP_LEN strlen(HEADER_SEP)

    string AddHeader(const string& str){
        string s = to_string(str.size());
        s += HEADER_SEP;
        s += str;
        s += HEADER_SEP;
        return s;
    }

    string RemoveHeader(const string& str, int len){
        string res = str.substr(str.size() - HEADER_SEP_LEN - len, len);
        return res;
    }
    
    int ReadPackage(int sock, string& inbuffer, string* package){
        //读取
        char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer - 1), 0);
        if(s <= 0)
            return -1;
        buffer[s] = 0;
        inbuffer += buffer;
        //分析
        auto pos = inbuffer.find(HEADER_SEP);
        if(pos == string::npos)
            return 0;
        string lenOfStr = inbuffer.substr(0, pos);
        int len = Util::toInt(lenOfStr);
        int lenOfPackage = lenOfStr.size() + len + 2 * HEADER_SEP_LEN;
        if(inbuffer.size() < lenOfPackage)
            return 0;
        //拿到完整string
        *package = inbuffer.substr(0,lenOfPackage);
        inbuffer.erase(0, lenOfPackage);
        return len;
    }

    class Request{
    public:
        Request(){}
        Request(int x, int y, char op):_x(x), _y(y), _op(op){}

        //struct -> string : _x _op _y
        bool Serialize(string* outStr){
            *outStr = "";

#ifdef MYSELF
            string x_string = to_string(_x);
            string y_string = to_string(_y);

            *outStr = x_string + SEP + _op + SEP + y_string;

#else
            Json::Value root;
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            Json::StyledWriter writer;
            *outStr = writer.write(root);

#endif
            return true;
        }

        //string ->struct
        bool Deserialize(const string& inStr){

#ifdef MYSELF
            vector<string> result;
            Util::StringSplit(inStr, SEP, &result);
            if(result.size() != 3)
                return false;
            if(result[1].size() != 1)
                return false;
            _x = Util::toInt(result[0]);
            _y = Util::toInt(result[2]);
            _op = result[1][0];

#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(inStr, root);
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();

#endif
            return true;
        }

        ~Request(){}

        int _x;
        int _y;
        char _op;
    };

    class Response{
    public:
        Response(){}
        Response(int result, int code): _result(result), _code(code){

        }

        bool Serialize(string* outStr){
            *outStr = "";

#ifdef MYSELF
            string res_string = to_string(_result);
            string code_string = to_string(_code);

            *outStr = res_string + SEP + code_string;

#else
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;
            Json::StyledWriter writer;
            *outStr = writer.write(root);

#endif
            return true;
        }

        bool Deserialize(const string& inStr){

#ifdef MYSELF
            vector<string> result;
            Util::StringSplit(inStr, SEP, &result);
            if(result.size() != 2)
                return false;
            _result = Util::toInt(result[0]);
            _code = Util::toInt(result[1]);

#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(inStr, root);
            _result = root["result"].asInt();
            _code = root["code"].asInt();

#endif
            return true;
        }

        ~Response(){}

        int _result;
        int _code;
    };
}